package com.iwuyc.tools.commons.util.image;

import com.iwuyc.tools.commons.util.image.bo.ImageInfo;
import com.iwuyc.tools.commons.util.image.bo.ZoomImageInfo;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

/**
 * 图片的工具类
 *
 * @author Neil
 * @version 1.0.0
 * @since 2023-07-14
 */
@Slf4j
public class ImageHelper {
    private ImageHelper() {

    }

    /**
     * 根据提供的文件实例，获取图片基本信息
     *
     * @param file 图片文件实例
     * @return 获取到的图片文件信息
     * @throws IOException 流异常
     */
    public static ImageInfo getImageInfo(File file) throws IOException {
        try (final FileInputStream in = new FileInputStream(file)) {
            return getImageInfo(in);
        }
    }

    /**
     * 获取图片基本信息
     *
     * @param in 数据输入流，遵循谁提供谁关闭的原则。由调用方自行关闭
     * @return 获取到的图片文件信息
     * @throws IOException 流异常
     */
    public static ImageInfo getImageInfo(InputStream in) throws IOException {
        if (null == in) {
            throw new NullPointerException("输入流不允许为null");
        }

        try (final ImageInputStream imageInputStream = ImageIO.createImageInputStream(in)) {

            final Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(imageInputStream);
            if (!imageReaders.hasNext()) {
                log.warn("未找到合适的图片读取程序，请确认是否支持该图片格式。");
                throw new IllegalArgumentException("未找到合适的图片读取程序，请确认是否支持该图片格式。");
            }

            final ImageReader imageReader = imageReaders.next();
            if (imageReader.getInput() == null) {
                imageReader.setInput(imageInputStream);
            }
            final int width = imageReader.getWidth(0);
            final int height = imageReader.getHeight(0);

            final ImageInfo result = new ImageInfo();
            result.setWidth(width);
            result.setHeight(height);
            result.setType(imageReader.getFormatName().toLowerCase());

            return result;
        }
    }

    /**
     * 图片缩放计算，至少保留两个像素点
     *
     * @param source     待缩放的图片信息
     * @param targetSpec 目标规格，宽跟高至少要提供一个
     * @return 缩放的目标大小
     */
    public static ZoomImageInfo zoomScaleCalc(ImageInfo source, ImageInfo targetSpec) {
        return zoomScaleCalc(source, targetSpec, 2);
    }

    /**
     * 图片缩放计算，至少保留两个像素点
     *
     * @param source      待缩放的图片信息
     * @param targetSpec  目标规格，宽跟高至少要提供一个
     * @param minMinPixel 最小保留的像素点数
     * @return 缩放的目标大小
     */
    public static ZoomImageInfo zoomScaleCalc(ImageInfo source, ImageInfo targetSpec, int minMinPixel) {
        final double zoomScale;
        if (targetSpec.getWidth() > 0) {
            double targetWidth = targetSpec.getWidth();
            zoomScale = targetWidth / source.getWidth();
        } else if (targetSpec.getHeight() > 0) {
            double targetHeight = targetSpec.getHeight();
            zoomScale = targetHeight / source.getHeight();
        } else {
            throw new IllegalArgumentException("请至少提供目标宽或高信息。");
        }

        final ZoomImageInfo result = new ZoomImageInfo();
        final int targetWidth = Math.max((int) (source.getWidth() * zoomScale), minMinPixel);
        final int targetHeight = Math.max((int) (source.getHeight() * zoomScale), minMinPixel);
        result.setZoomScale(zoomScale);
        result.setWidth(targetWidth);
        result.setHeight(targetHeight);
        return result;
    }


}
